package com.zjun.demo.experimentaldemo.utils

import com.clj.fastble.utils.HexUtil
import java.util.Locale

object HexUtil {

    private val DIGITS_LOWER: CharArray = charArrayOf(
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    )

    private val DIGITS_UPPER: CharArray = charArrayOf(
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    )

    fun encodeHex(data: ByteArray?): CharArray? {
        return encodeHex(data, true)
    }

    fun encodeHex(data: ByteArray?, toLowerCase: Boolean): CharArray? {
        return encodeHex(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
    }

    private fun encodeHex(data: ByteArray?, toDigits: CharArray): CharArray? {
        if (data == null) return null
        val l = data.size
        val out = CharArray(l shl 1)
        var i = 0
        var j = 0
        while (i < l) {
            out[j++] = toDigits[(0xF0 and data[i].toInt()) ushr 4]
            out[j++] = toDigits[0x0F and data[i].toInt()]
            i++
        }
        return out
    }


    fun encodeHexStr(data: ByteArray?): String {
        return encodeHexStr(data, true)
    }

    fun encodeHexStr(data: ByteArray?, toLowerCase: Boolean): String {
        return encodeHexStr(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
    }


    private fun encodeHexStr(data: ByteArray?, toDigits: CharArray): String {
        return String(encodeHex(data, toDigits)!!)
    }

    fun formatHexString(data: ByteArray?): String? {
        return formatHexString(data, false)
    }

    fun formatHexString(data: ByteArray?, addSpace: Boolean): String? {
        if (data == null || data.size < 1) return null
        val sb = StringBuilder()
        for (i in data.indices) {
            var hex = Integer.toHexString(data[i].toInt() and 0xFF)
            if (hex.length == 1) {
                hex = "0$hex"
            }
            sb.append(hex)
            if (addSpace) sb.append(" ")
        }
        return sb.toString().trim { it <= ' ' }
    }

    fun decodeHex(data: CharArray): ByteArray {
        val len = data.size

        if ((len and 0x01) != 0) {
            throw RuntimeException("Odd number of characters.")
        }

        val out = ByteArray(len shr 1)

        // two characters form the hex value.
        var i = 0
        var j = 0
        while (j < len) {
            var f = toDigit(data[j], j) shl 4
            j++
            f = f or toDigit(data[j], j)
            j++
            out[i] = (f and 0xFF).toByte()
            i++
        }

        return out
    }

    private fun toDigit(ch: Char, index: Int): Int {
        val digit = ch.digitToIntOrNull(16) ?: -1
        if (digit == -1) {
            throw RuntimeException(
                "Illegal hexadecimal character " + ch
                        + " at index " + index
            )
        }
        return digit
    }


    /**
     * 十六进制String转换成Byte[]
     * @param hexStringParam the hex string
     * @return byte[]
     */
    fun hexStringToBytes(hexStringParam: String?): ByteArray? {
        var hexString = hexStringParam
        if (hexString.isNullOrBlank()) {
            return null
        }
        hexString = hexString.uppercase(Locale.ROOT)
        val length = hexString.length / 2
        val hexChars = hexString.toCharArray()
        val d = ByteArray(length)
        for (i in 0 until length) {
            val pos = i * 2
            d[i] = (charToByte(hexChars[pos]).toInt() shl 4 or charToByte(hexChars[pos + 1]).toInt()).toByte()
        }
        return d
    }


    /**
     * Convert char to byte
     * @param c char
     * @return byte
     */
    private fun charToByte(c: Char): Byte {
        return "0123456789ABCDEF".indexOf(c).toByte()
    }

    fun extractData(data: ByteArray, position: Int): String {
        return HexUtil.formatHexString(byteArrayOf(data[position]))
    }


    private var testHexString: String =
        "59484b010066000000010700007b22636f6465223a2230222c226465766963654e616d65223a2241657269616c2058222c22646576696365506f7369746f6e223a22e5aeb6222c22646576696365556964223a22222c226572726f724d7367223a22222c226d6f64654964223a22222c226d6f64654e616d65223a22222c226d6f64656c536e223a22222c2270737754797065223a22575041222c2273686172654964223a22222c2274696d655a6f6e65223a22417369612f5368616e67686169222c22757365724964223a2234313131313430222c22776966694e616d65223a2241554d494f532de4b880e68192e7a791222c227769666950617373776f7264223a22383445652a255c75303032362e23227d23"

    /**
     * 按协议长度解析示例
     */
    fun dataAnalysis() {
//        val magic = hexToAscii(testHexString.substring(0, 6))
//        val version = reverseHex(testHexString.substring(6, 10)).toInt(16)
//        val command = reverseHex(testHexString.substring(10, 18)).toInt(16)
//        val lengthHex = testHexString.substring(18, 26)
//        val dsfsdf = Integer.parseInt(lengthHex.substring(6, 8), 16)
//        val lengthReverseHex = reverseHex(lengthHex)
//        val length = "0107".toInt(16)
//        val body =
//            hexToAscii("7b22636f6465223a2230222c226465766963654e616d65223a2241657269616c2058222c22646576696365506f7369746f6e223a22e5aeb6222c22646576696365556964223a22222c226572726f724d7367223a22222c226d6f64654964223a22222c226d6f64654e616d65223a22222c226d6f64656c536e223a22222c2270737754797065223a22575041222c2273686172654964223a22222c2274696d655a6f6e65223a22417369612f5368616e67686169222c22757365724964223a2234313131313430222c22776966694e616d65223a2241554d494f532de4b880e68192e7a791222c227769666950617373776f7264223a22383445652a255c75303032362e23227d")
//        val body1 =
//            hexToAscii("7b22636f6465223a2230222c226465766963654e616d65223a2241657269616c2058222c22646576696365506f7369746f6e223a22e5aeb6222c22646576696365556964223a22222c226572726f724d7367223a22222c226d6f64654964223a22222c226d6f64654e616d65223a22222c226d6f64656c536e223a22222c2270737754797065223a22575041222c2273686172654964223a22222c2274696d655a6f6e65223a22417369612f5368616e67686169222c22757365724964223a2234313131313430222c22776966694e616d65223a2241554d494f532de4b880e68192e7a791222c227769666950617373776f7264223a22383445652a255c75303032362e23227d")
//
//        val sdf = String("84Ee*%&.#".toByteArray(), Charsets.UTF_8)
//        sdf
        val dsfsdf =bytesToHexString(unlong2H2bytes(102))


        val versionHex = bytesToHexString(unlong2H2bytes(1))!!.substring(0,4)
        val commandHex = bytesToHexString(unlong2H2bytes(102))!!.substring(0,8)
        val sizeHex = bytesToHexString(unlong2H2bytes(265))!!.substring(0,8)
        sizeHex
    }

    /**
     * long类型转byte[] (小端)
     * @param n
     * @return
     */
    fun unlong2H2bytes(n: Long): ByteArray {
        val b = ByteArray(8)
        b[0] = (n and 0xffL).toByte()
        b[1] = (n shr 8 and 0xffL).toByte()
        b[2] = (n shr 16 and 0xffL).toByte()
        b[3] = (n shr 24 and 0xffL).toByte()
        b[4] = (n shr 32 and 0xffL).toByte()
        b[5] = (n shr 40 and 0xffL).toByte()
        b[6] = (n shr 48 and 0xffL).toByte()
        b[7] = (n shr 56 and 0xffL).toByte()
        return b
    }


//    /**
//     * 16进制字符串大端转小端
//     * @param bigEndianHex
//     * @return
//     */
//    fun convertToLittleEndian(bigEndianHex: String): String {
//        // 检查输入是否为偶数长度
//        if (bigEndianHex.length % 2 != 0) {
//            throw IllegalArgumentException("Input must have an even number of characters.");
//        }
//
//        // 将16进制字符串分割为每两个字符
//        val bytePairs = bigEndianHex.split("(?<=\\G..)");
//
//        // 反转字符对并重新连接
//        val littleEndianHex = StringBuilder();
//        for (int i = bytePairs.size - 1; i >= 0; i--) {
//            littleEndianHex.append(bytePairs[i]);
//        }
//
//        for(i in 0 )
//        return littleEndianHex.toString().uppercase(Locale.ROOT);
//    }

    /** 这里我们可以将byte转换成int，然后利用Integer.toHexString(int)来转换成16进制字符串。
     * @param src byte[] data
     * @return hex string
     */
    fun bytesToHexString(src: ByteArray?): String? {
        val stringBuilder = StringBuilder()
        if (src == null || src.isEmpty()) {
            return null
        }
        for (element in src) {
            val v = element.toInt() and 0xFF
            val hv = Integer.toHexString(v)
            if (hv.length < 2) {
                stringBuilder.append(0)
            }
            stringBuilder.append(hv.lowercase(Locale.getDefault()))
        }
        return stringBuilder.toString()
    }


    /**
     * 大端转小端 或者 小端转大端
     *
     * @param hex
     * @return
     */
    fun reverseHex(hex: String): String {
        val chars = hex.toCharArray()
        if (hex.length % 2 == 0) {
            val chars1 = CharArray(hex.length)
            for (i in 0 until chars.size / 2) {
                chars1[i * 2 + 1] = chars[chars.size - 1 - i * 2]
                chars1[i * 2] = chars[chars.size - 1 - (i * 2 + 1)]
            }
            return String(chars1)
        } else {
            return hex
        }
    }

    /**
     * 16进制转Ascii
     *
     * @param hexStr
     * @return Ascii
     */
    fun hexToAscii(hexStr: String): String {
        val output = StringBuilder()
        var i = 0
        while (i < hexStr.length) {
            val str = hexStr.substring(i, i + 2)
            output.append(str.toInt(16).toChar())
            i += 2
        }
        return output.toString()
    }

}